import {
  cadAppErrorLog,
  cadAppLog,
  cadAppWarnLog,
  withFeature,
} from '@amcax/base';
import { CloseOutlined } from '@ant-design/icons';
import * as Toast from '@radix-ui/react-toast';
import React, { Dispatch, SetStateAction, useState } from 'react';
import { ReactComponent as ErrorIcon } from './icons/error.svg';
import { ReactComponent as InfoIcon } from './icons/info.svg';
import { ReactComponent as SuccessIcon } from './icons/success.svg';
import { ReactComponent as WarningIcon } from './icons/warning.svg';

interface ToastEntity {
  id: number;
  type: string;
  message: string;
  timeout?: number;
}

export class MessageTip {
  static setToasts: Dispatch<SetStateAction<ToastEntity[]>>;

  static info = withFeature(
    'show-info-message',
    (message: string) => this.showToast('info', message),
    cadAppLog,
  );
  static error = withFeature(
    'show-error-message',
    (message: string) => this.showToast('error', message),
    cadAppErrorLog,
  );
  static success = withFeature(
    'show-success-message',
    (message: string) => this.showToast('success', message),
    (message: string) => cadAppLog('Success: ' + message),
  );
  static warning = withFeature(
    'show-warning-message',
    (message: string) => this.showToast('warning', message),
    cadAppWarnLog,
  );

  static showToast(type: string, message: string, timeout = 3000) {
    const id = Date.now();
    const newToast: ToastEntity = { id, type, message };

    this.setToasts((prevToasts) => [...prevToasts, newToast]);

    if (timeout > 0) {
      newToast.timeout = setTimeout(() => {
        this.closeToast(id);
      }, timeout) as unknown as number;
    }
  }

  static closeToast(id: number) {
    this.setToasts((prevToasts) => prevToasts.filter((t) => t.id !== id));
  }

  static destroy() {
    this.setToasts([]);
  }
}

export function ToastContainer() {
  const [toasts, setToasts] = useState<ToastEntity[]>([]);

  MessageTip.setToasts = setToasts;

  const toastTypeIcons: Record<string, React.ReactNode> = {
    info: <InfoIcon />,
    error: <ErrorIcon />,
    success: <SuccessIcon />,
    warning: <WarningIcon />,
  };

  const toastTypeStyles: Record<string, string> = {
    info: ' border-[#228be6] bg-[#f0f8ff]',
    error: 'border-[#ec5b56] bg-[#fff1f0]',
    warning: 'border-[#fda414] bg-[#fff8ed]',
    success: 'border-[#12b886] bg-[#ebfaf5]',
  };

  return (
    <Toast.Provider swipeDirection='up'>
      {
        // render the toasts, limiting to the last 5
        toasts.slice(-5).map((toast) => (
          <Toast.Root
            key={toast.id}
            className={`relative flex bg-white p-4 shadow-lg border rounded-[6px] ${toastTypeStyles[toast.type]}`}
            open={true}
          >
            <div className='flex flex-row items-center flex-1 min-w-0'>
              <Toast.Title className='text-[15px] font-medium text-slate12 flex items-center gap-x-2'>
                {toastTypeIcons[toast.type]}
              </Toast.Title>
              <Toast.Description className='ml-2 text-[15px] break-words whitespace-pre-line flex-1'>
                {toast.message}
              </Toast.Description>
            </div>
            <Toast.Close asChild>
              <button
                className='ml-2 inline-flex items-center justify-center rounded px-2.5 text-green11 hover:shadow-green8 focus:shadow-green8'
                onClick={() => MessageTip.closeToast(toast.id)}
              >
                <CloseOutlined />
              </button>
            </Toast.Close>
          </Toast.Root>
        ))
      }
      <Toast.Viewport className='fixed bottom-24 right-0 z-[2147483647] m-0 flex w-[560px] max-w-[100vw] list-none flex-col gap-2.5 p-4 outline-none' />
    </Toast.Provider>
  );
}
